.\" Copyright (c) 2007 by Sun Microsystems, Inc.  All rights reserved.
.\" Copyright 2017 Joyent, Inc.
.\" The contents of this file are subject to the terms of the
.\" Common Development and Distribution License (the "License").
.\" You may not use this file except in compliance with the License.
.\"
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
.\" or http://www.opensolaris.org/os/licensing.
.\" See the License for the specific language governing permissions
.\" and limitations under the License.
.\"
.\" When distributing Covered Code, include this CDDL HEADER in each
.\" file and include the License file at usr/src/OPENSOLARIS.LICENSE.
.\" If applicable, add the following below this CDDL HEADER, with the
.\" fields enclosed by brackets "[]" replaced with your own identifying
.\" information: Portions Copyright [yyyy] [name of copyright owner]
.Dd March 13, 2022
.Dt USCSI 4I
.Os
.Sh NAME
.Nm uscsi
.Nd user SCSI command interface
.Sh SYNOPSIS
.In sys/scsi/impl/uscsi.h
.Fo ioctl
.Fa "int filedes"
.Fa "int request"
.Fa "struct uscsi_cmd *cmd"
.Fc
.Sh DESCRIPTION
The
.Nm
command is very powerful and somewhat dangerous; therefore it
has some permission restrictions.
See
.Sx WARNINGS
for more details.
.Pp
Drivers supporting this
.Xr ioctl 2
provide a general interface allowing user-level applications to cause individual
.Sy SCSI
commands to be directed to a particular
.Sy SCSI
or
.Sy ATAPI
device under control of that driver.
The
.Nm
command is supported by the
.Xr sd 4D
driver for
.Sy SCSI
disks and
.Sy ATAPI
CD-ROM drives, and by the
.Xr st 4D
driver for
.Sy SCSI
tape drives.
.Nm
may also be supported by other device drivers; see the
specific device driver manual page for complete information.
.Pp
Applications must not assume that all Solaris disk device drivers support the
.Nm
ioctl command.
The
.Sy SCSI
command may include a data transfer
to or from that device, if appropriate for that command.
Upon completion of the command, the user application can determine how many
bytes were transferred and the status returned by the device.
Also, optionally, if the command returns a
Check Condition status, the driver will automatically issue a Request Sense
command and return the sense data along with the original status.
See the
.Sy USCSI_RQENABLE
flag below for this Request Sense processing.
The
.Vt uscsi_cmd
structure is defined in
.In sys/scsi/impl/uscsi.h
and includes the following members:
.Bd -literal -offset 2n
int uscsi_flags;              /* read, write, etc. see below */
short uscsi_status;           /* resulting status */
short uscsi_timeout;          /* Command Timeout */
caddr_t uscsi_cdb             /* CDB to send to target */
caddr_t uscsi_bufaddr;        /* i/o source/destination */
size_t uscsi_buflen;          /* size of i/o to take place*/
size_t uscsi_resid;           /* resid from i/o operation */
uchar_t uscsi_cdblen;         /* # of valid CDB bytes */
uchar_t uscsi_rqlen;          /* size of uscsi_rqbuf */
uchar_t uscsi_rqstatus;       /* status of request sense cmd */
uchar_t uscsi_rqresid;        /* resid of request sense cmd */
caddr_t uscsi_rqbuf;          /* request sense buffer */
void *uscsi_reserved_5;       /* Reserved for future use */
.Ed
.Pp
The fields of the
.Vt uscsi_cmd
structure have the following meanings:
.Bl -tag -width uscsi_reserved_5
.It Sy uscsi_flags
The
.Sy I/O
direction and other details of how to carry out the
.Sy SCSI
command.
Possible values are described below.
.It Fa uscsi_status
The
.Sy SCSI
status byte returned by the device is returned in this field.
.It Fa uscsi_timeout
Time in seconds to allow for completion of the command.
.It Fa uscsi_cdb
A pointer to the
.Sy SCSI
CDB (command descriptor block) to be transferred to the device in command phase.
.It Fa uscsi_bufaddr
The user buffer containing the data to be read from or written to the device.
.It Sy uscsi_buflen
The length of
.Fa uscsi_bufaddr .
.It Fa uscsi_resid
If a data transfer terminates without transferring the entire requested amount,
the remainder, or residue, is returned in this field.
.It Fa uscsi_cdblen
The length of the
.Sy SCSI
CDB to be transferred to the device in command phase.
.It Fa uscsi_rqlen
The length of
.Fa uscsi_rqbuf ,
the application's Request Sense buffer.
.It Fa uscsi_rqstatus
The
.Sy SCSI
status byte returned for the Request Sense command executed
automatically by the driver in response to a Check Condition status return.
.It Fa uscsi_rqresid
The residue, or untransferred data length, of the Request Sense data transfer
(the number of bytes, less than or equal to
.Fa uscsi_rqlen ,
which were not filled with sense data).
.It Fa uscsi_rqbuf
Points to a buffer in application address space to which the results of an
automatic Request Sense command are written.
.It Fa uscsi_reserved_5
Reserved for future use.
.El
.Pp
The
.Fa uscsi_flags
field defines the following:
.Bd -literal -offset 2n
USCSI_WRITE                   /* send data to device */
USCSI_SILENT                  /* no error messages */
USCSI_DIAGNOSE                /* fail if any error occurs */
USCSI_ISOLATE                 /* isolate from normal commands */
USCSI_READ                    /* get data from device */
USCSI_ASYNC                   /* set bus to asynchronous mode */
USCSI_SYNC                    /* return bus to sync mode if possible */
USCSI_RESET                   /* reset target */
USCSI_RESET_TARGET            /* reset target */
USCSI_RESET_LUN               /* reset logical unit */
USCSI_RESET_ALL               /* reset all targets */
USCSI_RQENABLE                /* enable request sense extensions */
USCSI_RENEGOT                 /* renegotiate wide/sync on next I/O */
.Ed
.Pp
The
.Fa uscsi_flags
bits have the following interpretation:
.Bl -tag -width USCSI_RESET_TARGET
.It Dv USCSI_WRITE
Data will be written from the initiator to the target.
.It Dv USCSI_SILENT
The driver should not print any console error messages or warnings regarding
failures associated with this
.Sy SCSI
command.
.It Dv USCSI_DIAGNOSE
The driver should not attempt any retries or other recovery mechanisms if this
.Sy SCSI
command terminates abnormally in any way.
.It Dv USCSI_ISOLATE
This
.Sy SCSI
command should not be executed with other commands.
.It Dv USCSI_READ
Data will be read from the target to the initiator.
.It Dv USCSI_ASYNC
Set the
.Sy SCSI
bus to asynchronous mode before running this command.
.It Dv USCSI_SYNC
Set the
.Sy SCSI
bus to synchronous mode before running this command.
.It Dv USCSI_RESET
Send a
.Sy SCSI
bus device reset message to this target.
.It Dv USCSI_RESET_TARGET
Same as USCSI_RESET.
Use this flag to request TARGET RESET.
.Po
.Dv USCSI_RESET
is maintained only for compatibility with old applications
.Pc .
.It Dv USCSI_RESET_LUN
Send a
.Sy SCSI
logical unit reset message to this target.
.It Dv USCSI_RESET_ALL
.Dv USCSI_RESET_ALL ,
.Dv USCSI_RESET/USCSI_RESET_TARGET ,
and
.Dv USCSI_RESET_LUN
are
mutually exclusive options and issuing them in any simultaneous combination
will result in implementation-dependent behavior
When a USCSI reset request is combined with other
.Sy SCSI
commands, the following semantics take effect:
If the
.Dv USCSI RESET
flag is specified, the other fields (other than
.Fa uscsi_flags )
in the
.Vt uscsi_cmd
are ignored.
The
.Fa uscsi_cdblen
field
.Em must
be set to zero.
.It Dv USCSI_RQENABLE
Enable Request Sense extensions.
If the user application is prepared to receive
sense data, this bit must be set, the fields
.Fa uscsi_rqbuf
and
.Fa uscsi_rqbuflen
must be non-zero, and the
.Fa uscsi_rqbuf
must point to memory writable by the application.
.It Dv USCSI_RENEGOT
Tells USCSI to renegotiate wide mode and synchronous transfer speed before the
transmitted SCSI command is executed.
This flag in effect tells the target driver to pass the
.Dv FLAG_RENEGOTIATE_WIDE_SYNC
flag in the SCSI packet
before passing the command to an adapter driver for transport.
See the
.Xr scsi_pkt 9S
flag
.Dv FLAG_RENEGOTIATE_WIDE_SYNC
for more information.
.El
.Pp
The
.Vt uscsi_xfer_t
is a type definition that corresponds to a 64-bit unsigned integer.
It should be used for the
.Dv USCSIMAXXFER
ioctls.
This is
used for determining the maximum transfer size that can be performed in a single
.Dv USCSICMD
ioctl.
If the SCSI request is larger than the specified size,
then it may not work, depending on the hardware platform.
.Sh IOCTLS
The
.Fn ioctl
supported by drivers providing the
.Nm
interface is:
.Bl -tag -width USCSIMAXXFER
.It Dv USCSICMD
The argument is a pointer to a
.Vt uscsi_cmd
structure.
The
.Sy SCSI
device addressed by that driver is selected, and given the
.Sy SCSI
command addressed by
.Fa uscsi_cdb .
If this command requires a data phase, the
.Fa uscsi_buflen
and
.Fa uscsi_bufaddr
fields must be set appropriately; if data phase occurs, the
.Fa uscsi_resid
is returned as the number of bytes not transferred.
The status of the command, as returned by the device, is returned in the
.Fa uscsi_status
field.
If the command terminates with Check Condition
status, and Request Sense is enabled, the sense data itself is returned in
.Fa uscsi_rqbuf .
The
.Fa uscsi_rqresid
provides the residue of the Request Sense data transfer.
.It Dv USCSIMAXXFER
The argument is a pointer to a
.Vt uscsi_xfer_t
value.
The maximum transfer size that can be used with the
.Dv USCSICMD
ioctl for the current device will be returned in the
.Vt uscsi_xfer_t .
.Pp
Not all devices which support the
.Dv USCSICMD
ioctl also support the
.Dv USCSIMAXXFER
ioctl.
.El
.Sh ERRORS
.Bl -tag -width EINVAL
.It Er EINVAL
A parameter has an incorrect, or unsupported, value.
.It Er EIO
An error occurred during the execution of the command.
.It Er EPERM
A process without root credentials tried to execute the
.Dv USCSICMD
or
.Dv USCSIMAXXFER
ioctl.
.It Er EFAULT
The
.Vt uscsi_cmd
itself, the
.Fa uscsi_cdb ,
the
.Fa uscsi_buf ,
the
.Fa uscsi_rqbuf ,
or the
.Vt uscsi_xfer_t
point to an invalid address.
.El
.Sh STABILITY
Committed
.Sh SEE ALSO
.Xr ioctl 2 ,
.Xr sd 4D ,
.Xr st 4D ,
.Xr attributes 7
.Rs
.%T ANSI Small Computer System Interface-2 (SCSI-2)
.Re
.Sh WARNINGS
The
.Nm
command is very powerful, but somewhat dangerous, and so its
use is restricted to processes running as root, regardless of the file
permissions on the device node.
The device driver code expects to own the device state, and
.Nm
commands can change the state of the device and confuse the device driver.
It is best to use
.Nm
commands only with no side effects, and avoid commands such as Mode Select, as
they may cause damage to data stored on the drive or system panics.
Also, as the commands are not checked in any way by the device driver, any block
may be overwritten, and the block numbers are absolute block numbers on the
drive regardless of which slice number is used to send the command.
.Pp
The
.Nm
interface is not recommended for very large data transfers
(typically more than 16MB).
If the requested transfer size exceeds the maximum transfer size of the DMA
engine, it will not be broken up into multiple transfers and DMA errors may
result.
The
.Dv USCSIMAXXFER
ioctl can be used to determine the maximum transfer size.
.Pp
The
.Dv USCSICMD
ioctl associates a
.Vt struct uscsi_cmd
with a device by using an open file descriptor to the device.
Other APIs might provide the same
.Vt struct uscsi_cmd
programming interface, but perform device association in some other manner.
